<template>
  <div class="app-container">
    <!-- 搜索栏 -->
    <el-card shadow="never">
      <el-form ref="queryFormRef" :model="queryParams" :inline="true">
        <el-form-item label="服务名称" prop="serviceName">
          <el-input
            v-model="queryParams.serviceName"
            placeholder="请输入服务名称"
            clearable
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
          <el-button :icon="Refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-card shadow="never" style="margin-top: 10px">
      <template #header>
        <el-button type="success" :icon="Plus" @click="handleCreate">新增服务</el-button>
        <el-button type="danger" :icon="Delete" :disabled="!multiple" @click="handleDelete()">
          删除
        </el-button>
      </template>

      <!-- 服务列表 -->
      <el-table
        v-loading="loading"
        :data="serviceList"
        border
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column prop="id" label="ID" width="80" />
        <el-table-column
          prop="serviceName"
          label="服务名称"
          min-width="120"
          show-overflow-tooltip
        />
        <el-table-column prop="version" label="版本号" width="100" />

        <el-table-column prop="status" label="服务状态" width="100">
          <template #default="scope">
            <el-tag :type="getServiceStatusTagType(scope.row.status)">
              {{ getServiceStatusLabel(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="type" label="服务类型" width="100" />
        <el-table-column prop="path" label="服务路径" min-width="150" show-overflow-tooltip />
        <el-table-column prop="port" label="端口" width="80" />
        <el-table-column
          prop="description"
          label="服务描述"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column label="操作" fixed="right" width="420" align="center">
          <template #default="scope">
            <el-space :size="8" alignment="center">
              <el-button size="small" type="primary" round @click="handleUpdate(scope.row.id)">
                <el-icon><Edit /></el-icon>
                编辑
              </el-button>

              <template v-if="scope.row.status === 'WAITING' || scope.row.status === 'FAIL'">
                <el-button size="small" type="success" round @click="startService(scope.row)">
                  <el-icon><Plus /></el-icon>
                  启动
                </el-button>
              </template>
              <template v-else>
                <el-button size="small" type="warning" round @click="stopService(scope.row)">
                  <el-icon><Delete /></el-icon>
                  停止
                </el-button>
              </template>

              <el-button size="small" type="info" round @click="restartService(scope.row)">
                <el-icon><Refresh /></el-icon>
                重启
              </el-button>

              <el-button size="small" type="primary" round @click="viewLog(scope.row)">
                <el-icon><Document /></el-icon>
                日志
              </el-button>

              <el-dropdown trigger="click">
                <el-button size="small" round>
                  <el-icon><MoreFilled /></el-icon>
                  更多
                </el-button>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item @click="viewConfig(scope.row)">
                      <el-icon><Setting /></el-icon>
                      配置
                    </el-dropdown-item>
                    <el-dropdown-item divided @click="handleDelete(scope.row.id)">
                      <el-icon><Delete /></el-icon>
                      删除
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </el-space>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <pagination
        v-if="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        :total="total"
        @pagination="handleQuery"
      />
    </el-card>

    <!-- 新增/编辑抽屉 -->
    <el-drawer
      v-model="drawer.visible"
      :title="drawer.title"
      size="50%"
      direction="rtl"
      @close="closeDrawer"
    >
      <el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="120px">
        <el-form-item label="CICD配置" prop="cicdConfigId">
          <el-select
            v-model="formData.cicdConfigId as any"
            placeholder="请选择CICD配置"
            clearable
            filterable
          >
            <el-option
              v-for="config in localConfigs"
              :key="config.id!"
              :label="config.name ? `${config.name}（${config.host}）` : config.host!"
              :value="config.id!"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="服务名称" prop="serviceName">
          <el-input v-model="formData.serviceName" placeholder="请输入服务名称" />
        </el-form-item>
        <el-form-item label="版本号" prop="version">
          <el-input v-model="formData.version" placeholder="请输入版本号" />
        </el-form-item>
        <el-form-item label="服务描述" prop="description">
          <el-input v-model="formData.description" type="textarea" placeholder="请输入服务描述" />
        </el-form-item>
        <el-form-item label="服务类型" prop="type">
          <el-input v-model="formData.type" placeholder="请输入服务类型" />
        </el-form-item>
        <el-form-item label="服务路径" prop="path">
          <el-input v-model="formData.path" placeholder="请输入服务路径" />
        </el-form-item>
        <el-form-item label="端口" prop="port">
          <el-input v-model.number="formData.port" type="number" placeholder="请输入端口" />
        </el-form-item>
        <el-form-item label="配置文件路径" prop="configPath">
          <el-input v-model="formData.configPath" placeholder="请输入配置文件路径" />
        </el-form-item>
        <el-form-item label="日志文件路径" prop="logPath">
          <el-input v-model="formData.logPath" placeholder="请输入日志文件路径" />
        </el-form-item>
        <el-form-item label="检查间隔(秒)" prop="checkInterval">
          <el-input
            v-model.number="formData.checkInterval"
            type="number"
            placeholder="请输入检查间隔"
          />
        </el-form-item>
        <el-form-item label="检查超时时间" prop="checkTimeout">
          <el-input
            v-model.number="formData.checkTimeout"
            type="number"
            placeholder="请输入检查超时时间"
          />
        </el-form-item>
        <el-form-item label="检查失败次数" prop="checkFailures">
          <el-input
            v-model.number="formData.checkFailures"
            type="number"
            placeholder="请输入检查失败次数"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer" style="text-align: right">
          <el-button @click="closeDrawer">取 消</el-button>
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
        </div>
      </template>
    </el-drawer>

    <!-- 操作确认弹框 -->
    <el-dialog
      v-model="state.operationDialog.visible"
      :title="state.operationDialog.title"
      :before-close="cancelOperation"
      width="30%"
      :close-on-click-modal="!state.operationDialog.isExecuting"
      :close-on-press-escape="!state.operationDialog.isExecuting"
    >
      <div v-if="!state.operationDialog.isExecuting">
        <span>{{ state.operationDialog.message }}</span>
      </div>
      <div v-else class="operation-progress">
        <el-progress
          :percentage="state.operationDialog.progress"
          :status="state.operationDialog.progress === 100 ? 'success' : undefined"
          :stroke-width="8"
          class="progress-bar"
        />
        <div class="progress-message">
          {{ state.operationDialog.statusMessage }}
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button v-if="!state.operationDialog.isExecuting" @click="cancelOperation">
            取 消
          </el-button>
          <el-button
            v-if="!state.operationDialog.isExecuting"
            type="primary"
            @click="confirmOperation"
          >
            确 定
          </el-button>
          <el-button v-else type="primary" disabled>执行中...</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 日志查看对话框 -->
    <el-dialog
      v-model="state.logDialog.visible"
      :title="state.logDialog.title"
      :before-close="closeLogDialog"
      width="80%"
      :close-on-click-modal="!state.logDialog.loading"
      :close-on-press-escape="!state.logDialog.loading"
    >
      <div v-if="state.logDialog.loading">
        <el-empty description="连接中..." />
      </div>
      <div v-else>
        <!-- 日志工具栏 -->
        <div class="log-toolbar" style="margin-bottom: 16px">
          <el-button type="primary" :icon="Refresh" size="small" @click="refreshLogs">
            刷新日志
          </el-button>
          <el-button type="success" size="small" @click="clearLogs">清空日志</el-button>
          <el-button type="info" size="small" @click="testLogDisplay">测试显示</el-button>
          <el-button type="warning" size="small" @click="debugLogState">调试状态</el-button>

          <el-divider direction="vertical" />

          <el-select
            v-model="state.logDialog.filterLevel"
            size="small"
            style="width: 110px"
            placeholder="级别"
          >
            <el-option label="全部" value="ALL" />
            <el-option label="ERROR" value="ERROR" />
            <el-option label="WARN" value="WARN" />
            <el-option label="INFO" value="INFO" />
            <el-option label="DEBUG" value="DEBUG" />
          </el-select>

          <el-input
            v-model="state.logDialog.keyword"
            size="small"
            placeholder="关键字过滤"
            clearable
            style="width: 180px; margin-left: 8px"
          />

          <el-input-number
            v-model="state.logDialog.fontSize"
            :min="10"
            :max="24"
            size="small"
            style="width: 120px; margin-left: 8px"
          />

          <el-divider direction="vertical" />

          <el-switch
            v-model="state.logDialog.wrap"
            size="small"
            inline-prompt
            active-text="自动换行"
            inactive-text="单行"
          />

          <el-divider direction="vertical" />

          <el-button size="small" @click="state.logDialog.filterLevel = 'ERROR'">
            只看 ERROR
          </el-button>
          <el-button size="small" @click="state.logDialog.filterLevel = 'WARN'">
            只看 WARN
          </el-button>

          <el-divider direction="vertical" />

          <el-button size="small" @click="copyAllLogs">复制全部</el-button>
          <el-button size="small" @click="downloadLogs">导出TXT</el-button>
          <span style="margin-left: 10px; font-size: 12px; color: #666">
            连接状态: {{ state.logDialog.eventSource ? "已连接" : "未连接" }} | 日志行数:
            {{ displayLogLines.length }} / {{ state.logDialog.logLines.length }} | 加载状态:
            {{ state.logDialog.loading ? "连接中" : "已就绪" }}
          </span>
        </div>

        <!-- 日志内容 -->
        <div
          ref="logContainerRef"
          class="log-content"
          style="max-height: 400px; padding: 12px; overflow-x: auto; overflow-y: auto"
        >
          <div class="log-lines">
            <div
              v-for="(line, index) in displayLogLines"
              :key="index"
              class="log-line"
              :class="getLogLineClass(line)"
              :style="{
                whiteSpace: state.logDialog.wrap ? 'pre-wrap' : 'pre',
                wordWrap: state.logDialog.wrap ? 'break-word' : 'normal',
                fontSize: state.logDialog.fontSize + 'px',
                margin: '0',
                fontFamily: 'Courier New, monospace',
                padding: '2px 0',
              }"
            >
              {{ line }}
            </div>
            <div v-if="displayLogLines.length === 0" class="no-logs">暂无匹配日志</div>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, toRefs, computed, nextTick } from "vue";
import { ElMessage, ElMessageBox, type FormInstance } from "element-plus";
import {
  Search,
  Refresh,
  Plus,
  Delete,
  Edit,
  Document,
  Setting,
  MoreFilled,
} from "@element-plus/icons-vue";
import ServiceManagerAPI, {
  type BuildServiceManagerVo,
  type BuildServiceManagerForm,
  type BuildWorkFlowPageQuery,
} from "@/api/serviceManager/index";
import CIcdConfigAPI, { type CicdConfigVO } from "@/api/build/cicdConfig";
import { useRouter } from "vue-router";
import { getAccessToken } from "@/utils/auth";

const router = useRouter();

const queryFormRef = ref<FormInstance>();
const dataFormRef = ref<FormInstance>();
const logContainerRef = ref<HTMLElement | null>(null);
const displayLogLines = computed(() => {
  const lines = state.logDialog.logLines;
  const level = state.logDialog.filterLevel;
  const kw = (state.logDialog.keyword || "").toLowerCase().trim();

  const matchLevel = (line: string) => {
    const up = line.toUpperCase();
    if (level === "ALL") return true;
    if (level === "ERROR") return up.includes("ERROR") || up.includes("EXCEPTION");
    if (level === "WARN") return up.includes("WARN");
    if (level === "INFO") return up.includes("INFO");
    if (level === "DEBUG") return up.includes("DEBUG");
    return true;
  };

  return lines.filter((l) => matchLevel(l) && (kw ? l.toLowerCase().includes(kw) : true));
});

const state = reactive({
  loading: true,
  ids: [] as number[],
  multiple: true,
  total: 0,
  queryParams: {
    pageNum: 1,
    pageSize: 10,
  } as BuildWorkFlowPageQuery,
  serviceList: [] as BuildServiceManagerVo[],
  cicdConfigList: [] as CicdConfigVO[],
  drawer: {
    title: "",
    visible: false,
  },
  formData: {} as BuildServiceManagerForm,
  rules: {
    serviceName: [{ required: true, message: "服务名称不能为空", trigger: "blur" }],
    cicdConfigId: [{ required: true, message: "请选择一个CICD配置", trigger: "change" }],
  },
  // 操作状态管理
  operationStates: new Map<number, { loading: boolean; progress: number; message: string }>(),
  // 操作确认弹框
  operationDialog: {
    visible: false,
    title: "",
    message: "",
    operation: null as (() => Promise<void>) | null,
    currentService: null as BuildServiceManagerVo | null,
    // 进度状态
    isExecuting: false,
    progress: 0,
    statusMessage: "",
  },
  // 日志查看对话框
  logDialog: {
    visible: false,
    title: "",
    serviceName: "",
    cicdConfigId: 0,
    id: 0,
    logContent: "",
    logLines: [] as string[], // 新增：使用数组存储日志行
    loading: false,
    eventSource: null as EventSource | null,
    filterLevel: "ALL" as "ALL" | "INFO" | "WARN" | "ERROR" | "DEBUG",
    keyword: "",
    fontSize: 14,
    wrap: false,
  },
});

const { loading, multiple, total, queryParams, serviceList, drawer, formData, rules } =
  toRefs(state);

const localConfigs = computed(() =>
  state.cicdConfigList.filter((c) => c.deployType === "local" && c.id != null)
);

// 状态选项和映射
const serviceStatusOptions = [
  { value: "RUNNING", label: "运行中", type: "success" },
  { value: "FAIL", label: "失败", type: "danger" },
  { value: "WAITING", label: "待发布", type: "info" },
];
type TagType = "success" | "danger" | "info" | "warning" | "primary";
function mapServiceStatus(status: string) {
  switch (status) {
    case "Running":
      return "RUNNING";
    case "Failed":
      return "FAIL";
    case "Pending":
    case "Waiting":
      return "WAITING";
    default:
      return status;
  }
}
function getServiceStatusLabel(status: string) {
  const found = serviceStatusOptions.find((s) => s.value === status);
  return found ? found.label : status;
}
function getServiceStatusTagType(status: string): TagType {
  const found = serviceStatusOptions.find((s) => s.value === status);
  const type = found?.type;
  if (
    type === "success" ||
    type === "danger" ||
    type === "info" ||
    type === "warning" ||
    type === "primary"
  ) {
    return type;
  }
  return "info";
}

// 日志行样式分类
function getLogLineClass(line: string) {
  const upper = line.toUpperCase();
  if (upper.includes("ERROR") || upper.includes("EXCEPTION")) return "level-error";
  if (upper.includes("WARN")) return "level-warn";
  if (upper.includes("INFO")) return "level-info";
  if (upper.includes("DEBUG")) return "level-debug";
  return "";
}

// 追加日志分片，处理 \r 覆盖与 ANSI 颜色码
function appendLogChunk(chunk: string) {
  // 去除 ANSI 颜色码（手动解析，避免正则控制字符告警）
  const stripAnsiManual = (s: string) => {
    let result = "";
    for (let i = 0; i < s.length; i++) {
      const code = s.charCodeAt(i);
      if (code === 27 /* ESC */ && s[i + 1] === "[") {
        // 跳过直到 'm'（SGR 结束）
        i += 2;
        while (i < s.length && s[i] !== "m") {
          i++;
        }
        continue;
      }
      result += s[i];
    }
    return result;
  };
  const normalized = stripAnsiManual(chunk);

  // 先按 \n 分段，再逐段处理 \r 覆盖
  const parts = normalized.split(/\n/);
  for (let i = 0; i < parts.length; i++) {
    let part = parts[i];
    if (part === "") continue;
    // 如果包含回车符，取最后一个 \r 之后的内容视为覆盖当前行
    if (part.includes("\r")) {
      part = part.substring(part.lastIndexOf("\r") + 1);
      if (state.logDialog.logLines.length === 0) {
        state.logDialog.logLines.push(part);
      } else {
        state.logDialog.logLines[state.logDialog.logLines.length - 1] = part;
      }
    } else {
      // 正常追加为新行
      state.logDialog.logLines.push(part);
    }
  }
  state.logDialog.logContent = state.logDialog.logLines.join("\n");
}

/** 查询 */
function handleQuery() {
  state.loading = true;
  ServiceManagerAPI.getPage(state.queryParams)
    .then((data) => {
      // 状态映射和端口类型转换
      state.serviceList = data.list.map((item: any) => ({
        ...item,
        status: mapServiceStatus(item.status),
        port: item.port !== undefined && item.port !== null ? Number(item.port) : undefined,
      }));
      state.total = data.total;
    })
    .finally(() => {
      state.loading = false;
    });
}

/** 重置查询 */
function resetQuery() {
  queryFormRef.value?.resetFields();
  handleQuery();
}

/** 多选 */
function handleSelectionChange(selection: any) {
  state.ids = selection.map((item: any) => item.id);
  state.multiple = !selection.length;
}

/** 新增 */
function handleCreate() {
  state.drawer = {
    title: "新增服务",
    visible: true,
  };
  state.formData = {
    serviceName: "",
    version: "",
    description: "",
    status: "WAITING",
    type: "",
    path: "",
    port: undefined as unknown as number, // 保证port为number类型
    configPath: "",
    logPath: "",
    startCommand: "",
    stopCommand: "",
    restartCommand: "",
    checkCommand: "",
    checkInterval: 300, // 默认5分钟
    checkTimeout: 30, // 默认30秒
    checkFailures: 3, // 默认3次
  };
}

/** 修改 */
async function handleUpdate(id: number) {
  state.drawer = {
    title: "修改服务",
    visible: true,
  };
  const data = await ServiceManagerAPI.getFormData(id);
  state.formData = {
    ...data,
    port: data.port !== undefined && data.port !== null ? Number(data.port) : undefined,
  };
}

/** 提交 */
function handleSubmit() {
  dataFormRef.value?.validate((valid: any) => {
    if (valid) {
      if (state.formData.id) {
        ServiceManagerAPI.update(state.formData.id, state.formData).then(() => {
          ElMessage.success("修改成功");
          closeDrawer();
          handleQuery();
        });
      } else {
        ServiceManagerAPI.add(state.formData).then(() => {
          ElMessage.success("新增成功");
          closeDrawer();
          handleQuery();
        });
      }
    }
  });
}

/** 删除 */
function handleDelete(id?: number) {
  const serviceIds = id ? String(id) : state.ids.join(",");
  ElMessageBox.confirm(`是否确认删除服务编号为「${serviceIds}」的数据项?`, "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      ServiceManagerAPI.deleteByIds(serviceIds).then(() => {
        ElMessage.success("删除成功");
        handleQuery();
      });
    })
    .catch(() => ElMessage.info("已取消删除"));
}

/** 关闭抽屉 */
function closeDrawer() {
  state.drawer.visible = false;
  dataFormRef.value?.resetFields();
}

/** 加载CICD配置列表 */
async function loadCicdConfigs() {
  try {
    const data = await CIcdConfigAPI.getList();
    state.cicdConfigList = data;
  } catch (e) {
    console.error("加载CICD配置列表失败:", e);
    ElMessage.error("加载CICD配置列表失败");
  }
}

/** 占位函数 */
function startService(row: BuildServiceManagerVo) {
  state.operationDialog = {
    visible: true,
    title: "启动服务",
    message: `确定要启动服务「${row.serviceName}」吗？`,
    operation: () => performStartService(row),
    currentService: row,
    isExecuting: false,
    progress: 0,
    statusMessage: "",
  };
}

function stopService(row: BuildServiceManagerVo) {
  state.operationDialog = {
    visible: true,
    title: "停止服务",
    message: `确定要停止服务「${row.serviceName}」吗？`,
    operation: () => performStopService(row),
    currentService: row,
    isExecuting: false,
    progress: 0,
    statusMessage: "",
  };
}

function restartService(row: BuildServiceManagerVo) {
  state.operationDialog = {
    visible: true,
    title: "重启服务",
    message: `确定要重启服务「${row.serviceName}」吗？`,
    operation: () => performRestartService(row),
    currentService: row,
    isExecuting: false,
    progress: 0,
    statusMessage: "",
  };
}

// 执行启动服务
async function performStartService(row: BuildServiceManagerVo) {
  if (!row.id) {
    ElMessage.error("服务ID不存在，无法启动");
    return;
  }

  try {
    await ServiceManagerAPI.start(row.id);
    ElMessage.success(`已请求启动服务: ${row.serviceName}`);
    handleQuery();
  } catch {
    ElMessage.error(`启动服务失败: ${row.serviceName}`);
  }
}

// 执行停止服务
async function performStopService(row: BuildServiceManagerVo) {
  if (!row.id) {
    ElMessage.error("服务ID不存在，无法停止");
    return;
  }

  try {
    await ServiceManagerAPI.stop(row.id);
    ElMessage.success(`已请求停止服务: ${row.serviceName}`);
    handleQuery();
  } catch {
    ElMessage.error(`停止服务失败: ${row.serviceName}`);
  }
}

// 执行重启服务
async function performRestartService(row: BuildServiceManagerVo) {
  if (!row.id) {
    ElMessage.error("服务ID不存在，无法重启");
    return;
  }

  try {
    await ServiceManagerAPI.restart(row.id);
    ElMessage.success(`已请求重启服务: ${row.serviceName}`);
    handleQuery();
  } catch {
    ElMessage.error(`重启服务失败: ${row.serviceName}`);
  }
}

// 确认操作
async function confirmOperation() {
  if (state.operationDialog.operation) {
    state.operationDialog.isExecuting = true;
    state.operationDialog.progress = 0;
    state.operationDialog.statusMessage = "正在执行操作...";

    // 模拟进度更新
    const progressInterval = setInterval(() => {
      if (state.operationDialog.progress < 90) {
        state.operationDialog.progress = Math.floor(
          state.operationDialog.progress + Math.random() * 10
        );
        state.operationDialog.statusMessage = "正在执行操作...";
      }
    }, 200);

    try {
      await state.operationDialog.operation();
      clearInterval(progressInterval);
      state.operationDialog.progress = 100;
      state.operationDialog.statusMessage = "操作完成";

      setTimeout(() => {
        state.operationDialog.visible = false;
        state.operationDialog.isExecuting = false;
      }, 1000);
    } catch {
      clearInterval(progressInterval);
      state.operationDialog.progress = 100;
      state.operationDialog.statusMessage = "操作失败";

      setTimeout(() => {
        state.operationDialog.visible = false;
        state.operationDialog.isExecuting = false;
      }, 1000);
    }
  }
}

// 取消操作
function cancelOperation() {
  if (!state.operationDialog.isExecuting) {
    state.operationDialog.visible = false;
  }
}

function viewConfig(row: BuildServiceManagerVo) {
  if (!row.cicdConfigId) {
    ElMessage.error("缺少CICD配置ID，无法查看配置文件");
    return;
  }

  router.push({
    name: "ConfigFileView",
    params: { service: row.serviceName },
    query: {
      id: row.cicdConfigId,
      name: row.serviceName,
      deployType: "local",
    },
  });
}

function viewLog(row: BuildServiceManagerVo) {
  if (!row.id) {
    ElMessage.error("缺少服务ID，无法查看日志");
    return;
  }

  console.log("打开日志对话框:", row);

  // 显示日志查看对话框
  state.logDialog = {
    visible: true,
    title: `查看日志 - ${row.serviceName}`,
    serviceName: row.serviceName,
    cicdConfigId: row.cicdConfigId,
    id: row.id,
    logContent: "",
    logLines: [], // 初始化日志行数组
    loading: true,
    eventSource: null,
    filterLevel: "ALL",
    keyword: "",
    fontSize: 14,
    wrap: false,
  };

  // 延迟一下再加载日志，确保对话框已经渲染
  nextTick(() => {
    loadServiceLogs(row.id, row.serviceName);
  });
}

// 加载服务日志
async function loadServiceLogs(id: number, serviceName: string) {
  console.log("开始加载日志:", { id, serviceName });

  // 清空之前的日志内容
  state.logDialog.logContent = "";

  // 先尝试 EventSource 连接
  await tryEventSourceConnection(id, serviceName);

  // 如果 EventSource 失败，尝试 HTTP 请求
  if (!state.logDialog.eventSource) {
    await tryHttpRequest(id, serviceName);
  }
}

// 尝试 EventSource 连接
async function tryEventSourceConnection(id: number, serviceName: string) {
  const baseApi = import.meta.env.VITE_APP_BASE_API || "/api";
  const token = getAccessToken();
  const tokenQuery = token ? `?token=${encodeURIComponent(token)}` : "";
  const logUrl = `${baseApi}/serviceManager/${id}/${serviceName}/logs${tokenQuery}`;

  console.log("尝试 EventSource 连接:", logUrl);

  try {
    const eventSource = new EventSource(logUrl);

    // 设置连接超时
    const connectionTimeout = setTimeout(() => {
      console.log("EventSource 连接超时");
      eventSource.close();
      state.logDialog.loading = false;
      state.logDialog.logContent = "EventSource 连接超时，尝试 HTTP 请求...";
    }, 10000); // 10秒超时

    // 无数据超时：打开后若一段时间没有任何数据，则回退 HTTP
    let noDataTimer: number | null = null;

    // 监听连接打开
    eventSource.onopen = () => {
      console.log("EventSource 连接已建立");
      clearTimeout(connectionTimeout);
      state.logDialog.loading = false;
      state.logDialog.logContent = ""; // 清空初始文本，准备接收数据

      // 若打开后 3 秒仍未收到任何数据，则回退到 HTTP 请求
      if (noDataTimer) {
        clearTimeout(noDataTimer);
      }
      noDataTimer = window.setTimeout(async () => {
        if (state.logDialog.logLines.length === 0) {
          console.log("EventSource 已建立但无数据，回退 HTTP");
          eventSource.close();
          state.logDialog.eventSource = null;
          await tryHttpRequest(id, serviceName);
        }
      }, 3000);
    };

    // 监听消息
    eventSource.onmessage = (event) => {
      console.log("收到 EventSource 日志数据:", event.data);
      console.log("数据类型:", typeof event.data);
      console.log("数据长度:", event.data ? event.data.length : 0);
      console.log("原始事件对象:", event);

      if (event.data !== undefined && event.data !== null) {
        appendLogChunk(String(event.data));
        console.log("更新后的日志行数:", state.logDialog.logLines.length);
        console.log("当前日志行数组:", state.logDialog.logLines);

        // 强制触发 Vue 更新
        nextTick(() => {
          console.log("Vue 更新后的日志行数:", state.logDialog.logLines.length);
          // 自动滚动到底部
          const el = logContainerRef.value;
          if (el) {
            el.scrollTop = el.scrollHeight;
          }
        });
      }
    };

    // 某些后端会使用自定义事件名 'log'
    eventSource.addEventListener("log", (event: MessageEvent) => {
      if (event.data) {
        appendLogChunk(String(event.data));
        nextTick(() => {
          const el = logContainerRef.value;
          if (el) el.scrollTop = el.scrollHeight;
        });
      }
    });

    // 监听错误
    eventSource.onerror = async (error) => {
      console.error("EventSource 错误:", error);
      clearTimeout(connectionTimeout);
      if (noDataTimer) {
        clearTimeout(noDataTimer);
      }
      eventSource.close();
      state.logDialog.loading = false;
      state.logDialog.logContent = "EventSource 连接失败，尝试 HTTP 请求...";
      state.logDialog.eventSource = null;
      await tryHttpRequest(id, serviceName);
    };

    // 存储 EventSource 实例
    state.logDialog.eventSource = eventSource;
  } catch (error) {
    console.error("创建 EventSource 失败:", error);
    state.logDialog.logContent = "EventSource 创建失败，尝试 HTTP 请求...";
    await tryHttpRequest(id, serviceName);
  }
}

// 尝试 HTTP 请求
async function tryHttpRequest(id: number, serviceName: string) {
  console.log("尝试 HTTP 请求获取日志");

  try {
    const response = await ServiceManagerAPI.getLogs(id, serviceName);
    console.log("HTTP 请求成功:", response);

    if (response) {
      state.logDialog.logContent = response;
    } else {
      state.logDialog.logContent = "暂无日志数据";
    }

    state.logDialog.loading = false;
  } catch (error) {
    console.error("HTTP 请求失败:", error);
    state.logDialog.logContent = "获取日志失败，请检查网络连接或服务状态";
    state.logDialog.loading = false;
  }
}

// 刷新日志
function refreshLogs() {
  if (state.logDialog.id && state.logDialog.serviceName) {
    console.log("刷新日志");

    // 先断开现有连接
    if (state.logDialog.eventSource) {
      state.logDialog.eventSource.close();
      state.logDialog.eventSource = null;
    }

    // 重置状态
    state.logDialog.loading = true;
    state.logDialog.logContent = "";
    state.logDialog.logLines = [];

    // 重新加载日志
    loadServiceLogs(state.logDialog.id, state.logDialog.serviceName);
  }
}

// 清空日志
function clearLogs() {
  state.logDialog.logContent = "";
  state.logDialog.logLines = [];
  ElMessage.success("日志已清空");
}

// 复制全部日志
async function copyAllLogs() {
  const text = displayLogLines.value.join("\n");
  try {
    await navigator.clipboard.writeText(text);
    ElMessage.success("已复制到剪贴板");
  } catch {
    ElMessage.error("复制失败");
  }
}

// 导出日志为 TXT
function downloadLogs() {
  const text = displayLogLines.value.join("\n");
  const blob = new Blob([text], { type: "text/plain;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  const filename = `${state.logDialog.serviceName || "logs"}.txt`;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
  ElMessage.success("导出成功");
}

// 测试日志显示
function testLogDisplay() {
  const testData = `测试日志 ${new Date().toLocaleTimeString()}
这是一条测试日志消息
用于验证日志显示功能是否正常
EventSource 连接状态: ${state.logDialog.eventSource ? "已连接" : "未连接"}`;

  // 使用数组模式
  state.logDialog.logLines.push(testData);
  state.logDialog.logContent = state.logDialog.logLines.join("\n");
  ElMessage.success("测试数据已添加");
}

// 调试日志状态
function debugLogState() {
  console.log("=== 日志状态调试信息 ===");
  console.log("logDialog 状态:", state.logDialog);
  console.log("logLines 数组:", state.logDialog.logLines);
  console.log("logLines 长度:", state.logDialog.logLines.length);
  console.log("logContent:", state.logDialog.logContent);
  console.log("loading:", state.logDialog.loading);
  console.log("eventSource:", state.logDialog.eventSource);
  console.log("eventSource readyState:", state.logDialog.eventSource?.readyState);

  // 显示在页面上
  ElMessage.info(
    `日志行数: ${state.logDialog.logLines.length}, 连接状态: ${state.logDialog.eventSource ? "已连接" : "未连接"}`
  );
}

// 关闭日志对话框
function closeLogDialog() {
  console.log("关闭日志对话框");

  // 断开 EventSource 连接
  if (state.logDialog.eventSource) {
    console.log("断开 EventSource 连接");
    state.logDialog.eventSource.close();
    state.logDialog.eventSource = null;
  }

  state.logDialog.visible = false;
  state.logDialog.logContent = "";
  state.logDialog.logLines = [];
  state.logDialog.loading = false;
}

onMounted(() => {
  handleQuery();
  loadCicdConfigs();
});
</script>
<style scoped>
.app-container {
  padding: 12px;
}

/* 操作列按钮细节优化 */
.ops-buttons {
  white-space: nowrap;
}
.ops-buttons :deep(.el-button) {
  padding: 8px 14px;
}

/* 日志工具栏：保持一行，横向滚动 */
.log-toolbar {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  align-items: center;
  overflow-x: auto;
}
.log-toolbar > * {
  flex: 0 0 auto;
}

/* 日志主题优化 */
.log-content {
  color: #e5e7eb; /* gray-200 */
  background-color: #000000; /* true black */
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
}

.operation-progress {
  text-align: center;

  .progress-bar {
    margin-bottom: 16px;

    :deep(.el-progress-bar__outer) {
      background-color: #f0f2f5;
      border-radius: 10px;
    }

    :deep(.el-progress-bar__inner) {
      border-radius: 10px;
      transition: width 0.3s ease;
    }
  }

  .progress-message {
    font-size: 14px;
    font-weight: 500;
    color: #666;
  }
}

.log-lines {
  .log-line {
    padding: 2px 6px;
    border-bottom: 1px dashed rgba(255, 255, 255, 0.06);

    &:last-child {
      border-bottom: none;
    }

    &:hover {
      background-color: rgba(255, 255, 255, 0.04);
    }
  }

  .level-info {
    color: #60a5fa; /* blue-400 */
  }
  .level-warn {
    color: #f59e0b; /* amber-500 */
    background-color: rgba(245, 158, 11, 0.08);
  }
  .level-error {
    color: #f87171; /* red-400 */
    background-color: rgba(239, 68, 68, 0.08);
  }
  .level-debug {
    color: #34d399; /* emerald-400 */
  }

  .no-logs {
    padding: 20px;
    font-style: italic;
    color: rgba(255, 255, 255, 0.6);
    text-align: center;
  }
}
</style>
